home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Portable Patmos 1.1 / patmos-src / src / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-01  |  40.7 KB  |  1,702 lines  |  [TEXT/R*ch]

  1. /*
  2.  * BSD-style socket emulation library for the Mac
  3.  * Original author: Tom Milligan
  4.  * Current author: Charlie Reiman - creiman@ncsa.uiuc.edu
  5.  *
  6.  * This source file is placed in the public domian.
  7.  * Any resemblance to NCSA Telnet, living or dead, is purely coincidental.
  8.  *
  9.  *      National Center for Supercomputing Applications
  10.  *      152 Computing Applications Building
  11.  *      605 E. Springfield Ave.
  12.  *      Champaign, IL  61820
  13.  */
  14.  
  15. /*
  16.  *
  17.  *    The following calls are implemented
  18.  *
  19.  *        socket
  20.  *        bind
  21.  *        listen
  22.  *        accept
  23.  *        connect
  24.  *        read
  25.  *        recv
  26.  *        recvfrom
  27.  *        write
  28.  *        writev
  29.  *        send
  30.  *        sendto
  31.  *        select
  32.  *        close
  33.  *        getdtablesize
  34.  *        getsockname
  35.  *        getpeername
  36.  *        shutdown
  37.  *        fcntl(F_DUPFD)
  38.  *        fcntl(F_GETFL)
  39.  *        fcntl(F_SETFL,FNDELAY)
  40.  *        dup
  41.  *        dup2
  42.  *        ioctl(FIONBIO)
  43.  *        ioctl(FIONREAD)
  44.  *
  45.  *    Non-blocking I/O is supported. All calls which would block return
  46.  *    immediately with an 'error' indicating so. Select() may be used to
  47.  *    determine when an operation can be performed.
  48.  *
  49.  *    Ioctl(FIONBIO) or fcntl(F_SETFL,FNDELAY)  can be used to toggle or set
  50.  *  the blocking status of a socket.
  51.  *
  52.  *    In a blocking situation, accept() and read() return EWOULDBLOCK and 
  53.  *    refuse to do anything. Select() for read() to learn when a incoming 
  54.  *    connection is available. 
  55.  *
  56.  *    Connect() and write() (which shouldn't take too long anyway) start 
  57.  *    the operation and return EINPROGRESS. Select for write() to learn
  58.  *    when connect() has completed. Write() on a socket which is still
  59.  *    'inprogress' return EALREADY.
  60.  *
  61.  *
  62.  *    Socket operations are single threaded and half-duplex. Fixing this is
  63.  *    left as an execise for the reader. Shouldn't be a terrible problem
  64.  *    anyway. Read() never blocks and write() only blocks for long if there
  65.  *    is a problem.
  66.  *
  67.  *    Calls which find the socket busy will return EALREADY. These are
  68.  *    read() or write() with a connect() or write() in progress.
  69.  *
  70.  *
  71.  *    Socket options are not supported. Hence no setsockopt() and getsockopt() 
  72.  *    calls.
  73.  *
  74.  *
  75.  *  CR: I attempted to support OOB data for send and recv, but not promises are
  76.  *  made as I didn't have any immediate tests for them.
  77.  *
  78.  *
  79.  *    Readv() is not implemented.
  80.  *
  81.  *
  82.  *    All calls which encounter an error will set the global variable errno
  83.  *    to indicate the problem. Some common values for errno are...
  84.  *
  85.  *        EBADF        the socket parameter is not a valid socket descriptor.
  86.  *        
  87.  *        EFAULT       a pointer parameters is rubbish.
  88.  *        
  89.  *        EINVAL       a non-pointer parameters is rubbish.
  90.  *
  91.  *        ENOTCONN     the socket should be in a connected state for this 
  92.  *                   operation, but isn't.
  93.  *
  94.  *        EISCONN      the socket is already connected.
  95.  *
  96.  * ----------------- non-blocking I/O
  97.  *
  98.  *        EWOULDBLOCK  accept() or one of the read() calls would block. 
  99.  *
  100.  *        EINPROGRESS  connect() or one of the write() operations has been 
  101.  *                   started.
  102.  *
  103.  * ----------------- SINGLE THREAD
  104.  *
  105.  *        EALREADY     an operation is already in progress on the socket.
  106.  *
  107.  * ----------------
  108.  *
  109.  *        EBUG           an internal error occured.
  110.  */
  111.  
  112. #ifdef USEDUMP
  113. # pragma load "socket.dump"
  114.  
  115. #else
  116. # include <Events.h>
  117. # include <Types.h>
  118. # include <Stdio.h>
  119. # include <string.h>
  120. # include <s_types.h>
  121. # include <neti_in.h>
  122. # include <neterrno.h>
  123. # include <s_file.h>
  124. # include <s_ioctl.h>
  125. # include <s_socket.h>
  126. # include <s_time.h>
  127. # include <s_uio.h>
  128.  
  129. # include "sock_str.h"
  130. # include "sock_int.h"
  131.  
  132. #endif
  133.  
  134. #include "sock_ext.h"
  135.  
  136.  
  137. /*
  138.  *   GET YOUR GLOBALS HERE!
  139.  */
  140.  
  141. int defaultSpin(spin_msg msg,long param);
  142. SocketPtr sockets = NULL;            /* The socket table. */
  143. AllPb *pbList = NULL;                /* The pb array */
  144. short pbLast = 0;                    /* last pb used */
  145. StreamHashEntPtr streams = NULL;    /* The streams hash table */
  146. SpinFn spinroutine = (SpinFn) defaultSpin;    /* The spin routine. */ 
  147.  
  148. /*
  149.  *    s_socket(domain, type, protocol)
  150.  *
  151.  *        socket creates a MacTCP socket and returns a descriptor.
  152.  *                 
  153.  *        Domain must be AF_INET
  154.  *         
  155.  *        Type may be SOCK_STREAM to create a TCP socket or 
  156.  *        SOCK_DGRAM to create a UDP socket.
  157.  *                 
  158.  *        Protocol is ignored. (isn't it always?)
  159.  *                 
  160.  *        TCP sockets provide sequenced, reliable, two-way connection
  161.  *        based byte streams.
  162.  *
  163.  *        A TCP socket must be in a connected
  164.  *        state before any data may be sent or received on it. A 
  165.  *        connection to another socket is created with a connect() call
  166.  *        or the listen() and accept() calls.
  167.  *        Once connected, data may be transferred using read() and
  168.  *        write() calls or some variant of the send() and recv()
  169.  *        calls. When a session has been completed a close() may  be
  170.  *        performed.
  171.  *
  172.  *        
  173.  *        A UDP socket supports the exchange of datagrams (connectionless, 
  174.  *        unreliable messages of a fixed maximum length) with  
  175.  *        correspondents named in send() calls. Datagrams are
  176.  *        generally received with recv(), which returns the next
  177.  *        datagram with its return address.
  178.  *
  179.  *        An fcntl() or ioctl() call can be used to enable non-blocking I/O.
  180.  *
  181.  *        The return value is a descriptor referencing the socket or -1
  182.  *        if an error occurs, in which case global variable errno is
  183.  *        set to one of:
  184.  *
  185.  *            ENOMEM                Failed to allocate memory for the socket
  186.  *                              data structures.
  187.  *        
  188.  *            EAFNOSUPPORT         Domain wasn't AF_INET.
  189.  *
  190.  *            ESOCKTNOSUPPORT     Type wasn't SOCK_STREAM or SOCK_DGRAM.
  191.  *
  192.  *            EMFILE              The socket descriptor table is full.
  193.  */
  194. int s_socket(
  195.     Int4 domain,
  196.     Int4 type,
  197.     short protocol)
  198. {
  199.     SocketPtr sp;
  200.     int s;
  201.  
  202. #if    SOCK_DEBUG >= 3
  203.     dprintf("s_socket:\n");
  204. #endif
  205.  
  206.     sock_init();
  207.     
  208.     /*
  209.      * Support only Internet family
  210.      */
  211.     if ((domain != AF_INET) && (domain != AF_UNIX))
  212.         return(sock_err(EAFNOSUPPORT));
  213.         
  214.     switch(type) 
  215.     {
  216.         case SOCK_DGRAM:
  217.             protocol = IPPROTO_UDP;
  218.             break;
  219.         case SOCK_STREAM:
  220.             protocol = IPPROTO_TCP;
  221.             break;
  222.         default:
  223.             return(sock_err(ESOCKTNOSUPPORT));
  224.     }
  225.         
  226.     /*
  227.      *    Create a socket table entry 
  228.      */
  229.     s = sock_free_fd(0);        /* Get next free file descriptor */
  230.     if (s == -1)
  231.         return(sock_err(EMFILE));
  232.     sp = sockets+s;
  233.     sp->fd = s;
  234.     sp->protocol = protocol;
  235.     bzero(&sp->sa, sizeof(struct sockaddr_in));
  236.     bzero(&sp->peer, sizeof(struct sockaddr_in));
  237.     sp->sa.sin_family        = AF_INET;
  238.     sp->sa.sin_len            = sizeof(struct sockaddr_in);
  239.     sp->status                = SOCK_STATUS_USED;
  240.     sp->nonblocking            = false;
  241.  
  242.  
  243.     /* Create a new stream on the socket. */
  244.     switch(sp->protocol) 
  245.     {
  246.         case IPPROTO_UDP:
  247.             /* udp streams are not created until the last minute */
  248.             /* because we dont know if the caller wants to assign */
  249.             /* a special port number yet (via bind) and mactcp */
  250.             /* assigns udp port numbers at stream creation */
  251.             sp->sstate = SOCK_STATE_NO_STREAM;
  252.             break;
  253.  
  254.         case IPPROTO_TCP:
  255.             /* the tcp stream is created now because tcp port numbers */
  256.             /* are assigned during active/passiveOpen which is done */
  257.             /* during listen or connect */
  258.             sp->sstate = SOCK_STATE_UNCONNECTED;
  259.             if (sock_tcp_new_stream(sp) < 0)
  260.                 return(-1); /* sock_err already called */
  261.     }
  262.  
  263.     return(s);
  264. }
  265.  
  266.  
  267. /*
  268.  *    s_bind(s, name, namelen)
  269.  *
  270.  *        bind requests that the name (ip address and port) pointed to by 
  271.  *        name be assigned to the socket s.
  272.  *        
  273.  *        The return value is 0 on success or -1 if an error occurs,
  274.  *        in which case global variable errno is set to one of:
  275.  *
  276.  *        EAFNOSUPPORT        The address family in name is not AF_INET.
  277.  *        
  278.  *        EINVAL              The socket is already bound to an address.
  279.  *        
  280.  *        EADDRNOTAVAIL       The specified address is  not  available
  281.  *                             from the local machine. ie. the address
  282.  *                            portion of name was not this machine's address.
  283.  *
  284.  *        MacTCP does not separate name binding and connection establishment.
  285.  *        Therefore the port number is not verified, just stored for later use.
  286.  *
  287.  *        If a specific local port is not required, bind is optional in this
  288.  *        implementation.
  289.  */    
  290.  
  291. int s_bind( 
  292.     Int4 s, 
  293.     struct sockaddr *sa_name,
  294.     Int4 namelen)
  295. {
  296.     SocketPtr sp;
  297.     struct sockaddr_in *name=(struct sockaddr_in *)sa_name;
  298.  
  299.     struct timeval ktime;
  300.     struct timezone kzone;
  301.     gettimeofday(&ktime, &kzone);
  302.     
  303. #if    SOCK_DEBUG >= 3
  304.     dprintf("s_bind: bind %d to %08x/%d\n",
  305.         s, name->sin_addr.s_addr, name->sin_port);
  306. #endif
  307.  
  308.     if (! sock_good_fd(s))
  309.         return(sock_err(EBADF));
  310.     sp = sockets+s;
  311.         
  312.     if (namelen < sizeof(struct sockaddr_in))
  313.         return(sock_err(EINVAL));
  314.  
  315.     if (!goodptr(name)) 
  316.         return(sock_err(EFAULT));
  317.  
  318.     if ((name->sin_family != AF_INET) && (name->sin_family != AF_UNIX))
  319.         return(sock_err(EAFNOSUPPORT));
  320.  
  321.     if (sp->sa.sin_port != 0) /* already bound */
  322.         return(sock_err(EINVAL));
  323.  
  324.     /*
  325.      *    If client passed a local IP address, assure it is the right one
  326.      */
  327.     if (name->sin_addr.s_addr != 0) 
  328.     {
  329.         if (name->sin_addr.s_addr != xIPAddr())
  330.             return(sock_err(EADDRNOTAVAIL));
  331.     }
  332.  
  333.     /*
  334.      *    NOTE: can't check a TCP port for EADDRINUSE
  335.      *    just save the address and port away for connect or listen or...
  336.      */
  337.     sp->sa.sin_addr.s_addr = name->sin_addr.s_addr;
  338.     if (!name->sin_port) name->sin_port = (ktime.tv_sec&8191)+4000;
  339.     sp->sa.sin_port = name->sin_port;
  340.     return(0);
  341. }
  342.  
  343. /*
  344.  *    s_connect - initiate a connection on a MacTCP socket
  345.  *
  346.  *        If the parameter s is a UDP socket,
  347.  *        then  this  call specifies the address to  which  datagrams
  348.  *        are  to  be  sent, and the only address from which datagrams
  349.  *        are to be received.  
  350.  *             
  351.  *        If it is a TCP socket, then this call attempts to make a 
  352.  *        connection to another socket. The other socket is specified 
  353.  *        by an internet address and port.
  354.  *             
  355.  *        TCP sockets may successfully connect() only once;
  356.  *             
  357.  *        UDP sockets may use connect() multiple times to change
  358.  *        their association. UDP sockets may dissolve the association
  359.  *        by connecting to an invalid address, such as a null
  360.  *        address.
  361.  *        
  362.  *        If the connection or binding succeeds, then 0 is returned.
  363.  *        Otherwise a -1 is returned, and a more specific error code
  364.  *        is stored in errno.
  365.  *        
  366.  *        EAFNOSUPPORT        The address family in addr is not AF_INET.
  367.  *        
  368.  *        EHOSTUNREACH        The TCP connection came up half-way and 
  369.  *                          then failed.
  370.  *             
  371.  *    -------------- some day instead of EHOSTUNREACH -----------------
  372.  *        
  373.  *        EADDRNOTAVAIL       The specified address is not available
  374.  *                            on the remote machine.
  375.  *        
  376.  *        ETIMEDOUT           Connection establishment timed out
  377.  *                            without establishing a connection.
  378.  *        
  379.  *        ECONNREFUSED        The attempt to  connect  was  forcefully
  380.  *                            rejected.
  381.  *        
  382.  *        ENETUNREACH         The network is not reachable from here.
  383.  *        
  384.  *        EHOSTUNREACH        The host is not reachable from here.
  385.  *        
  386.  *        EADDRINUSE          The address is already in use.
  387.  */
  388. int s_connect(
  389.     Int4 s,
  390.     struct sockaddr *sa_addr,
  391.     Int4 addrlen)
  392. {
  393.     SocketPtr sp;
  394.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  395.     
  396. #if SOCK_DEBUG >= 2
  397.     dprintf("s_connect: connect %d to %08x/%d\n",
  398.         s, addr->sin_addr.s_addr, addr->sin_port);
  399. #endif
  400.     if (! sock_good_fd(s))
  401.         return(sock_err(EBADF));
  402.         
  403.     if (addrlen != sizeof(struct sockaddr_in))
  404.         return(sock_err(EINVAL));
  405.  
  406.     if (! goodptr(addr))
  407.         return(sock_err(EFAULT));
  408.  
  409.     if (addr->sin_family != AF_INET)
  410.         return(sock_err(EAFNOSUPPORT));
  411.  
  412.     sp = sockets+s;
  413.     switch(sp->protocol) 
  414.     {
  415.         case IPPROTO_UDP:
  416.             return(sock_udp_connect(sp,addr));
  417.  
  418.         case IPPROTO_TCP:
  419.             return(sock_tcp_connect(sp,addr));
  420.     }
  421. }
  422.  
  423. /*
  424.  *    s_listen()
  425.  *
  426.  *        To accept connections, a socket is first created  with
  427.  *        socket(), a backlog for incoming connections is specified
  428.  *        with listen() and then the  connections  are  accepted  with
  429.  *        accept(). The listen() call applies only to TCP sockets.
  430.  *        
  431.  *        The qlen parameter is supposed to define the maximum length
  432.  *        the queue of pending connections may grow to. It is ignored.
  433.  *        
  434.  *        A 0 return value indicates success; -1 indicates an error.
  435.  *        
  436.  *        EOPNOTSUPP          s is not a TCP socket.
  437.  */
  438. int s_listen(
  439.     Int4 s,
  440.     Int4 qlen)
  441. {
  442. #pragma unused(qlen)
  443.     SocketPtr sp;
  444.     
  445. #if SOCK_DEBUG >= 2
  446.     dprintf("listen: listen %d\n", s);
  447. #endif
  448.     if (! sock_good_fd(s))
  449.         return(sock_err(EBADF));
  450.         
  451.     sp = sockets+s;    
  452.     switch(sp->protocol) 
  453.     {
  454.         case IPPROTO_UDP:
  455.             return(sock_err(EOPNOTSUPP));
  456.         
  457.         case IPPROTO_TCP:
  458.             return(sock_tcp_listen(sp));
  459.     }
  460. }
  461.  
  462. /*
  463.  *    s_accept(s, addr, addrlen)
  464.  *
  465.  *        s is a socket that has been created with socket,  bind, listen.
  466.  *        
  467.  *        Accept  extracts the  first  connection  on the queue of pending 
  468.  *        connections, creates a new socket with the same properties of s 
  469.  *        and allocates  a  new  file  descriptor,  ns, for the socket.
  470.  *        
  471.  *        If no pending connections are present on the queue, and the socket
  472.  *        is not marked as non-blocking, accept blocks the caller until
  473.  *        a connection is present. 
  474.  *        
  475.  *        If the socket is marked non-blocking  and  no pending connections 
  476.  *        are present on the queue, accept returns an error EWOULDBLOCK.
  477.  *        
  478.  *        The accepted socket, ns, is used to read and write data to and
  479.  *        from the socket which connected to this one; it is not  used
  480.  *        to  accept  more connections.  The original socket s remains
  481.  *        open for accepting further connections.
  482.  *        
  483.  *        The argument addr is a result parameter that  is  filled  in
  484.  *        with  the  address of the connecting socket. The addrlen is 
  485.  *        a value-result  parameter; it should initially contain the
  486.  *        amount of space pointed to by addr; on return it will contain 
  487.  *        the actual length (in bytes) of the address returned.
  488.  *        
  489.  *        This call is used with TCP sockets only.
  490.  *        
  491.  *        It is possible to select a socket  for  the  purposes  of
  492.  *        doing an accept by selecting it for read.
  493.  *
  494.  *        Translation: To check and see if there is a connection pending,
  495.  *        call s_select and check for pending reads.
  496.  *        
  497.  *        The call returns -1 on error.  If it succeeds, it returns  a
  498.  *        non-negative  integer  that is a descriptor for the accepted
  499.  *        socket.
  500.  *        
  501.  *        EOPNOTSUPP          s is not a TCP socket.
  502.  *        
  503.  *        EMFILE              The socket descriptor table is full.
  504.  */
  505. int s_accept(
  506.     Int4 s,
  507.     struct sockaddr *sa_addr,
  508.     Int4 *addrlen)
  509. {
  510.     SocketPtr sp;
  511.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  512.  
  513. #if SOCK_DEBUG >= 2
  514.     dprintf("s_accept: %d\n", s);
  515. #endif
  516.     if (! sock_good_fd(s))
  517.         return(sock_err(EBADF));
  518.         
  519.     if (!goodptr(addr) || !goodptr(addrlen)) 
  520.         return(sock_err(EFAULT));
  521.  
  522.     if (*addrlen < 0) 
  523.         return(sock_err(EINVAL));
  524.  
  525.     if (sock_free_fd(0) == -1)
  526.         return(sock_err(EMFILE));
  527.  
  528.     sp = sockets+s;
  529.     switch(sp->protocol) 
  530.     {
  531.         case IPPROTO_UDP:
  532.             return(sock_err(EOPNOTSUPP));
  533.         case IPPROTO_TCP:
  534.             return(sock_tcp_accept(sp,addr,addrlen));
  535.     }
  536. }
  537.  
  538. /*
  539.  * s_accept_once
  540.  *
  541.  * A mac specific routine, designed to compenstate for a bug
  542.  * in MacTCP. If you close a passive, unconnected stream,
  543.  * MacTCP will generate an error. s_accept always creates
  544.  * a new listening (passive open) stream that will eventually
  545.  * need to be closed. s_accept_once does not create a new
  546.  * listening socket. It will return the same socket originally
  547.  * passed to it, and NO more connections will be accepted
  548.  * on the old listening port.
  549.  *
  550.  * Other than that, it is identical to s_accept.
  551.  */
  552. int s_accept_once(
  553.     Int4 s,
  554.     struct sockaddr *sa_addr,
  555.     Int4 *addrlen)
  556. {
  557.     SocketPtr sp;
  558.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  559.  
  560. #if SOCK_DEBUG >= 2
  561.     dprintf("s_accept: %d\n", s);
  562. #endif
  563.     if (! sock_good_fd(s))
  564.         return(sock_err(EBADF));
  565.         
  566.     if (!goodptr(addr) || !goodptr(addrlen)) 
  567.         return(sock_err(EFAULT));
  568.  
  569.     if (*addrlen < 0) 
  570.         return(sock_err(EINVAL));
  571.  
  572.     if (sock_free_fd(0) == -1)
  573.         return(sock_err(EMFILE));
  574.  
  575.     sp = sockets+s;
  576.     switch(sp->protocol) 
  577.     {
  578.         case IPPROTO_UDP:
  579.             return(sock_err(EOPNOTSUPP));
  580.         case IPPROTO_TCP:
  581.             {
  582.             int        returnCode;
  583.             
  584.             returnCode=sock_tcp_accept_once(sp,addr,addrlen);
  585.             return (returnCode ? returnCode : s );
  586.             }
  587.     }
  588. }
  589.  
  590. /*
  591.  *    s_close(s)
  592.  *
  593.  *        The close call destroys the socket s. If this is the last reference 
  594.  *        to the underlying MacTCP stream, then the stream will be released.
  595.  *    
  596.  *        A 0 return value indicates success; -1 indicates an error.
  597.  *
  598.  *        NOTE: if non-blocking I/O is enabled EWOULDBLOCK will be returned
  599.  *            if there are TCP writes in progress. (UDP writes are
  600.  *            performed synchronously.)
  601.  *
  602.  *              All reads are terminated and unread data is lost.
  603.  */
  604. int s_close(
  605.     Int4 s)
  606. {
  607.     int t;
  608.     SocketPtr sp;
  609.     int status;
  610.     
  611. #if SOCK_DEBUG >= 2
  612.     dprintf("s_close: %d\n", s);
  613. #endif
  614.     if (! sock_good_fd(s))
  615.         return(sock_err(EBADF));
  616.         
  617.     sp = sockets+s;
  618.  
  619.     /*
  620.      *    Look for duplicates of the socket.  Only close down the connection
  621.      *    if there are no duplicates(i.e. socket not dup'd).
  622.      */
  623.      for (t = 0; t < NUM_SOCKETS; t++) 
  624.      {
  625.          if (t == s)
  626.             continue;
  627.          if (!(sockets[t].status & SOCK_STATUS_USED))
  628.             continue;
  629.         else if (sockets[t].protocol == sp->protocol && sockets[t].stream == sp->stream )
  630.         {    /* found a duplicate */
  631. #if SOCK_DEBUG >= 3
  632.             dprintf("s_close: found a dup at %d(%d, don't close stream\n",
  633.                 t, sockets[t].protocol);
  634. #endif
  635.             sock_clear_fd(s);
  636.             return(0);
  637.         }
  638.     }
  639.  
  640.     /*
  641.      *    No duplicates, close the stream. 
  642.      */
  643.     switch(sp->protocol) 
  644.     {
  645.         case IPPROTO_UDP:
  646.             status = sock_udp_close(sp);
  647.             break;
  648.             
  649.         case IPPROTO_TCP:
  650.             status = sock_tcp_close(sp);
  651.             break;
  652.     }
  653.     if (status != EWOULDBLOCK)
  654.         sock_clear_fd(s);
  655.     return(status);
  656. }
  657.  
  658.  
  659. /*
  660.  *    s_read(s, buffer, buflen)
  661.  *
  662.  *    s_recv(s, buffer, buflen, flags)
  663.  *    
  664.  *    s_recvfrom(s, buffer, buflen, flags, from, fromlen)
  665.  *    
  666.  *        read() attempts to read nbytes of data from the socket s.  
  667.  *        
  668.  *        recv() and recvfrom() attempt to receive a message (ie a datagram) 
  669.  *        on the socket s. 
  670.  *
  671.  *        from returns the address of the socket which sent the message.
  672.  *        fromlen is the usual value-result length parameter. 
  673.  *        
  674.  *        Typically, read() is used with a TCP stream and recv() with
  675.  *        UDP where the idea of a message makes more sense. But in fact,
  676.  *        read() and recv() are equivalent.
  677.  *        
  678.  *        For UDP...
  679.  *            If a message (ie. datagram) is too long to fit in the supplied 
  680.  *            buffer, excess bytes will be discarded..
  681.  *
  682.  *            If no messages are available at the socket, the receive call
  683.  *            waits for a message to arrive, unless the socket is non-
  684.  *            blocking in which case -1 is returned with errno set to 
  685.  *            EWOULDBLOCK.
  686.  *
  687.  *        For TCP...
  688.  *            Regardless of non-blocking status, if less data is available
  689.  *            than has been requested, only that much data is returned.
  690.  *
  691.  *            If the socket is marked for non-blocking I/O, and the socket 
  692.  *            is empty, the operation will fail with the error EWOULDBLOCK.
  693.  *            Otherwise, the operation will block until data is available 
  694.  *            or an error occurs.
  695.  *
  696.  *            A return value of zero indicates that the stream has been
  697.  *            closed and all data has already been read. ie. end-of-file.
  698.  *        
  699.  *        Flags is ignored.
  700.  *        
  701.  *        If successful, the number of bytes actually received is
  702.  *        returned. Otherwise, a -1 is returned and the global variable
  703.  *        errno is set to indicate the error. 
  704.  *        
  705.  *        ESHUTDOWN    The socket has been shutdown for receive operations.
  706.  */
  707. int s_recvfrom(
  708.     Int4 s,
  709.     char *buffer,
  710.     Int4 buflen,
  711.     Int4 flags,
  712.     struct sockaddr *sa_from,
  713.     Int4 *fromlen);
  714.  
  715. int s_read(
  716.     Int4 s,
  717.     char *buffer,
  718.     Int4 buflen)
  719. {
  720.     int fromlen = 0;
  721.     return(s_recvfrom(s, buffer, buflen, 0, NULL, (void *)&fromlen));
  722. }
  723.  
  724. int s_recv(
  725.     Int4 s,
  726.     char *buffer,
  727.     Int4 buflen,
  728.     Int4 flags)
  729. {
  730.     int fromlen = 0;
  731.     return(s_recvfrom(s, buffer, buflen, flags, NULL, (void *)&fromlen));
  732. }
  733.  
  734. int s_recvfrom(
  735.     Int4 s,
  736.     char *buffer,
  737.     Int4 buflen,
  738.     Int4 flags,
  739.     struct sockaddr *sa_from,
  740.     Int4 *fromlen)
  741. {
  742.     SocketPtr sp;
  743.     struct sockaddr_in *from=(struct sockaddr_in *)sa_from;
  744.  
  745. #if SOCK_DEBUG >= 3
  746.     dprintf ("s_recvfrom: %d\n", s);
  747. #endif
  748.     if (s < 0 || s >= NUM_SOCKETS)
  749.         return (sock_err (EBADF));
  750.         
  751.     sp = sockets+s;
  752.     if (! is_used (sp))
  753.         return (sock_err (EBADF));
  754.         
  755.     if (!goodptr(buffer))
  756.         return (sock_err (EFAULT));
  757.         
  758.     if (buflen <= 0)
  759.         return(sock_err(EINVAL));
  760.         
  761.     if (! (from == NULL || goodptr(from)) )
  762.         return(sock_err(EFAULT));
  763.         
  764.     if (! (fromlen == NULL || goodptr(fromlen)) )
  765.         return(sock_err(EFAULT));
  766.     else
  767.         if ( *fromlen < 0 )
  768.             return(sock_err(EINVAL));
  769.  
  770.     if (sock_noread(sp))
  771.         return(sock_err(ESHUTDOWN));
  772.  
  773.     switch(sp->protocol) 
  774.     {
  775.         case IPPROTO_UDP:
  776.             return(sock_udp_recv(sp, buffer, buflen, flags, from, (int *)fromlen));
  777.  
  778.         case IPPROTO_TCP:
  779.             return(sock_tcp_recv(sp, buffer, buflen, flags));
  780.     }
  781. }
  782.  
  783.  
  784. /*
  785.  *    s_write(s, buffer, buflen)
  786.  *
  787.  *    s_writev(s, iov, iovcnt)
  788.  *
  789.  *    s_send(s, buffer, buflen, flags)
  790.  *
  791.  *    s_sendto(s, buffer, buflen, flags, to, tolen)
  792.  *
  793.  *        write() attempts to write nbytes of data to the socket s from
  794.  *        the buffer pointed to by buffer.
  795.  *        
  796.  *        writev() gathers the output data from the buffers specified 
  797.  *        by the members of the iov array. Each iovec entry specifies 
  798.  *        the base address and length of an area in memory from which 
  799.  *        data should be written.
  800.  *        
  801.  *        send() and sendto() are used to transmit a message to another 
  802.  *        socket on the socket s.
  803.  *
  804.  *        Typically, write() is used with a TCP stream and send() with
  805.  *        UDP where the idea of a message makes more sense. But in fact,
  806.  *        write() and send() are equivalent.
  807.  *        
  808.  *        For UDP...
  809.  *
  810.  *          Write() and send() operations are completed as soon as the
  811.  *          data is placed on the transmission queue.???????
  812.  *
  813.  *            The address of the target is given by to.
  814.  *
  815.  *            The message must be short enough to fit into one datagram.
  816.  *        
  817.  *            Buffer space must be available to hold the message to be 
  818.  *            transmitted, regardless of its non-blocking I/O state.
  819.  *        
  820.  *        For TCP...
  821.  *            Write() and send() operations are not considered complete
  822.  *            until all data has been sent and acknowledged.
  823.  *
  824.  *            If a socket is marked for non-blocking I/O, the operation
  825.  *            will return an 'error' of EINPROGRESS.
  826.  *        
  827.  *            If the socket is not marked for non-blocking I/O, the write will
  828.  *            block until space becomes available.
  829.  *        
  830.  *        write() and send() may be used only when the socket is in a connected
  831.  *        state, sendto() may be used at any time.
  832.  *
  833.  *        Flags is ignored.
  834.  *        
  835.  *        These calls return the number of bytes sent, or -1 if an error 
  836.  *        occurred.
  837.  *        
  838.  *        EINVAL           The sum of the iov_len values in the iov array was
  839.  *                         greater than 65535 (TCP) or 65507 (UDP) or there
  840.  *                       were too many entries in the array (16 for TCP or
  841.  *                       6 for UDP).
  842.  *
  843.  *        ESHUTDOWN        The socket has been shutdown for send operations.
  844.  *        
  845.  *        EMSGSIZE         The message is too big to send in one datagram. (UDP)
  846.  *
  847.  *        ENOBUFS          The transmit queue is full. (UDP)
  848.  */
  849.  
  850. int s_really_send(
  851.     Int4 s,
  852.     char *buffer,
  853.     Int4 count,
  854.     Int4 flags,
  855.     struct sockaddr_in *to);
  856.  
  857. int s_write(
  858.     Int4 s,
  859.     char *buffer,
  860.     Int4 buflen)
  861. {
  862.     return(s_really_send(s, buffer, buflen, 0, NULL));
  863.  
  864. int s_writev(
  865.     Int4 s,
  866.     struct iovec *iov,
  867.     Int4 count)
  868. {    
  869.     int        result,tally=0;
  870.     
  871.     while (count--)
  872.         {
  873.         if ( !goodptr( iov ) )
  874.             return sock_err(EFAULT);
  875.         result= s_really_send(s, (char *)(iov->iov_base),
  876.                 (int)(iov->iov_len), 0, NULL);
  877.         if (result < 0)
  878.             return sock_err(result);
  879.         iov++;
  880.         tally+=result;
  881.         }
  882.     return tally;
  883.  
  884. int s_send(
  885.     Int4 s,
  886.     char *buffer,
  887.     Int4 buflen,
  888.     Int4 flags)
  889. {
  890.     return(s_really_send(s, buffer, buflen, flags, NULL));
  891.  
  892. int s_sendto (
  893.     Int4 s,
  894.     char *buffer,
  895.     Int4 buflen,
  896.     Int4 flags,
  897.     struct sockaddr *sa_to,
  898.     Int4 tolen)
  899. {
  900.     SocketPtr sp;
  901.     struct sockaddr_in *to=(struct sockaddr_in *)sa_to;
  902.  
  903.     if (s < 0 || s >= NUM_SOCKETS)
  904.         return (sock_err (EBADF));
  905.         
  906.     sp = sockets+s;
  907.     
  908.     if (! is_used (sp))
  909.         return (sock_err (EBADF));
  910.         
  911.     if (!goodptr(buffer))
  912.         return (sock_err (EFAULT));
  913.         
  914.     if (buflen <= 0)
  915.         return(sock_err(EINVAL));
  916.         
  917.     if (to != NULL && !goodptr(to))
  918.         return(sock_err(EFAULT));
  919.         
  920.     if (to != NULL && tolen < sizeof(struct sockaddr_in))
  921.         return(sock_err(EINVAL));
  922.  
  923.     return(s_really_send(s, buffer, buflen, flags, to));
  924. }
  925.  
  926. int s_sendmsg(Int4 s,struct msghdr *msg,Int4 flags) {
  927.     SocketPtr sp;
  928.     struct iovec *iov=NULL;
  929.     int tally=0,result,count;
  930.  
  931.     if (s < 0 || s >= NUM_SOCKETS)
  932.         return (sock_err (EBADF));
  933.         
  934.     sp = sockets+s;
  935.     
  936.     if (! is_used (sp))
  937.         return (sock_err (EBADF));
  938.     if (!goodptr(msg))
  939.         return (sock_err (EFAULT));
  940.     if ( msg->msg_name != NULL && !goodptr(msg->msg_name) ) 
  941.         return (sock_err (EFAULT));
  942.     if ( msg->msg_name != NULL && msg->msg_namelen < sizeof (struct sockaddr_in))
  943.         return (sock_err (EFAULT));
  944.     
  945.     count = msg->msg_iovlen;
  946.     iov = msg->msg_iov;
  947.     while ( count -- ) {
  948.         if ( !goodptr( iov ) )
  949.             return sock_err(EFAULT);
  950.         result= s_really_send(s, (char *)(iov->iov_base),
  951.                 (int)(iov->iov_len), flags,(struct sockaddr_in *)msg->msg_name);
  952.         if (result < 0)
  953.             return (sock_err(result));
  954.         iov++;
  955.         tally+=result;
  956.         }
  957.     return tally;
  958.     }
  959.  
  960. int s_really_send(
  961.     Int4 s,
  962.     char *buffer,
  963.     Int4 count,
  964.     Int4 flags,
  965.     struct sockaddr_in *to)
  966.     
  967.     {
  968.     SocketPtr    sp;
  969.     int            tally=0;
  970.  
  971. #if SOCK_DEBUG >= 2
  972.     dprintf("s_really_send: %d  %d bytes", s, count);
  973.     if (to != NULL)
  974.         dprintf(" to %08x/%d",to->sin_addr.s_addr,to->sin_port);
  975.     dprintf("\n");
  976. #endif
  977.     if (! sock_good_fd(s))
  978.         return(sock_err(EBADF));
  979.     sp = sockets+s;
  980.  
  981. #if SOCK_DEBUG >= 2
  982.     dprintf("state %d\n",sp->sstate);
  983.     dprintf("peer %08x/%d\n",sp->peer.sin_addr.s_addr,sp->peer.sin_port);
  984. #endif
  985.     
  986.     if (sock_nowrite(sp))
  987.         return(sock_err(ESHUTDOWN));
  988.  
  989.     switch(sp->protocol) 
  990.         {
  991.         case IPPROTO_UDP:
  992.             if (to == NULL && sp->sstate != SOCK_STATE_CONNECTED) 
  993.                 return(sock_err(ENOTCONN));
  994.             return(sock_udp_send(sp, to, buffer, count, flags));
  995.             break;
  996.             
  997.         case IPPROTO_TCP:
  998.             if (to != NULL) /* sendto */
  999.                 return(sock_err(EOPNOTSUPP));
  1000.             if (sp->sstate != SOCK_STATE_CONNECTED) 
  1001.                 return(sock_err(ENOTCONN));
  1002.             return ( sock_tcp_send(sp, buffer, count,0 ));
  1003.             break;
  1004.         }
  1005.     }
  1006.  
  1007.  
  1008. /*
  1009.  *    s_select(width, readfds, writefds, exceptfds, timeout)
  1010.  *
  1011.  *        select() examines the I/O descriptor  sets  whose  addresses
  1012.  *        are  passed  in  readfds,  writefds, and exceptfds to see if
  1013.  *        some of their descriptors are ready for reading,  ready  for
  1014.  *        writing, or have an exceptional condition pending.  width is
  1015.  *        the number of bits to be  checked  in  each  bit  mask  that
  1016.  *        represent  a file descriptor; the descriptors from 0 through
  1017.  *        width-1 in the  descriptor  sets  are  examined.   Typically
  1018.  *        width  has  the  value  returned by getdtablesize for the
  1019.  *        maximum number of file  descriptors.   On  return,  select
  1020.  *        replaces  the  given descriptor sets with subsets consisting
  1021.  *        of those descriptors that are ready for the requested opera-
  1022.  *        tion.  The total number of ready descriptors in all the sets
  1023.  *        is returned.
  1024.  *
  1025.  *        If timeout is not a NULL pointer,  it  specifies  a  maximum
  1026.  *        interval  to wait for the selection to complete.  If timeout
  1027.  *        is a NULL  pointer,  the  select  blocks  indefinitely.   To
  1028.  *        effect  a  poll,  the  timeout argument should be a non-NULL
  1029.  *        pointer, pointing to a zero-valued timeval structure.
  1030.  *
  1031.  *        Any of readfds, writefds, and exceptfds may be given as NULL
  1032.  *        pointers if no descriptors are of interest.
  1033.  *
  1034.  *        Using select to open a socket for reading is analogous  to
  1035.  *        performing an accept call.
  1036.  *
  1037.  *        select() returns the number of ready  descriptors  that  are
  1038.  *        contained  in  the  descriptor  sets,  or  -1  if  an  error
  1039.  *        occurred.  If the time limit expires then  select()  returns
  1040.  *        0.   If select() returns with an error the descriptor sets 
  1041.  *      will be unmodified.
  1042.  */
  1043. int s_select(
  1044.     Int4 width,
  1045.     fd_set *readfds,
  1046.     fd_set *writefds,
  1047.     fd_set *exceptfds,
  1048.     struct timeval *timeout)
  1049. {
  1050.     SocketPtr sp;
  1051.     long count;
  1052.     int s;
  1053.     long starttime, waittime;
  1054.     fd_set rd, wd, ed;
  1055.     int errorHappened;
  1056.  
  1057. #if SOCK_DEBUG >= 4
  1058.     dprintf("select:  socket: width %d\n",width);
  1059. #endif
  1060.     if (!goodptr(timeout) && timeout != NULL)
  1061.         return(sock_err(EFAULT));
  1062.     if (!goodptr(readfds) && readfds != NULL)
  1063.         return(sock_err(EFAULT));
  1064.     if (!goodptr(writefds) && writefds != NULL)
  1065.         return(sock_err(EFAULT));
  1066.     if (!goodptr(exceptfds) && exceptfds != NULL)
  1067.         return(sock_err(EFAULT));
  1068.         
  1069. #if SOCK_DEBUG >= 4
  1070.     dprintf("select: timeout %d sec, read %08x write %08x except %08x\n",
  1071.         (timeout ? timeout->tv_sec : 99999), 
  1072.         (readfds!=NULL ? *readfds : 0L),
  1073.         (writefds!=NULL ? *writefds : 0L),
  1074.         (exceptfds!=NULL ? *exceptfds : 0L));
  1075. #endif
  1076.  
  1077.     if (width > NUM_SOCKETS)    /* for now..xxx. */
  1078.         width = NUM_SOCKETS;
  1079.     count = 0;
  1080.     FD_ZERO(&rd);
  1081.     FD_ZERO(&wd);
  1082.     FD_ZERO(&ed);
  1083.  
  1084.     if (timeout) 
  1085.     {
  1086.         waittime = TVTOTICK(timeout->tv_sec,timeout->tv_usec);
  1087.         starttime = TickCount();
  1088.     }
  1089. #if SOCK_DEBUG >= 5
  1090.     dprintf("     starttime = %d(tics);  waittime = %d\n",starttime, waittime);
  1091. #endif
  1092.  
  1093.     do 
  1094.     {
  1095.         for (s = 0 , sp = sockets ; s < width ; ++s, ++sp) 
  1096.         {
  1097.             if (is_used(sp)) 
  1098.             {
  1099.                 errorHappened = 0;
  1100.                 
  1101.                 /* Check if there is data or connection available. */
  1102.                 if (readfds && FD_ISSET(s,readfds)) 
  1103.                 {
  1104.                         
  1105.                     switch(sp->protocol) 
  1106.                     {
  1107.                         case IPPROTO_UDP:
  1108.                             switch (sock_udp_can_recv(sp))
  1109.                             {
  1110.                                 case 1:
  1111.                                     FD_SET(s,&rd);
  1112.                                     ++count;
  1113.                                     break;
  1114.                                 case -1:
  1115.                                     errorHappened = 1;
  1116.                                     break;
  1117.                             }
  1118.                             break;
  1119.                 
  1120.                         case IPPROTO_TCP:
  1121.                     /* Must exit if stream is dead to avoid eternal lock up */
  1122.                             if (sock_tcp_can_read(sp) ) {
  1123.                                 FD_SET(s,&rd);
  1124.                                 ++count;
  1125.                                 } 
  1126.                             break;
  1127.                     }
  1128.                 }
  1129.                 if (writefds && FD_ISSET(s,writefds)) 
  1130.                 {
  1131.                     switch(sp->protocol) 
  1132.                     {
  1133.                         case IPPROTO_UDP:
  1134.                             switch (sock_udp_can_send(sp))
  1135.                             {
  1136.                                 case 1:
  1137.                                     FD_SET(s,&wd);
  1138.                                     ++count;
  1139.                                     break;
  1140.                                 case -1:
  1141.                                     errorHappened = 1;
  1142.                                     break;
  1143.                             }
  1144.                             break;
  1145.                 
  1146.                         case IPPROTO_TCP:
  1147.                             if (sock_tcp_can_write(sp))
  1148.                             {
  1149.                                 FD_SET(s,&wd);
  1150.                                 ++count;
  1151.                             }
  1152.                             break;
  1153.                     }
  1154.                 }
  1155.                 if (exceptfds && FD_ISSET(s,exceptfds)) 
  1156.                 {
  1157.                     if (errorHappened)  
  1158.                     {
  1159.                         FD_SET(s,&ed);
  1160.                         ++count;
  1161.                     }
  1162.                 }
  1163.             }
  1164.         }
  1165.         SPIN(false,SP_SELECT,0)
  1166.     } 
  1167.     while(count == 0 &&(timeout == 0 || TickCount() - starttime < waittime));
  1168.  
  1169.     if (readfds)             
  1170.         *readfds = rd;
  1171.     if (writefds)             
  1172.         *writefds = wd;
  1173.     if (exceptfds)             
  1174.         *exceptfds = ed;
  1175. #if SOCK_DEBUG >= 5
  1176.     dprintf("     elapsed = %d(tics)  count %d, read %08x write %08x except %08x\n",
  1177.         TickCount()-starttime,count,
  1178.         (readfds!=NULL ? *readfds : 0L),
  1179.         (writefds!=NULL ? *writefds : 0L),
  1180.         (exceptfds!=NULL ? *exceptfds : 0L));
  1181. #endif
  1182.     return(count);
  1183. }
  1184.     
  1185. /*
  1186.  *    s_getdtablesize()
  1187.  *
  1188.  *        The entries in the socket descriptor table are numbered with small
  1189.  *        integers starting at 0. getdtablesize returns the size of the 
  1190.  *        descriptor table.
  1191.  */
  1192. int s_getdtablesize()
  1193. {
  1194.     return(NUM_SOCKETS);
  1195. }
  1196.  
  1197. /*
  1198.  *    s_getsockname(s, name, namelen)
  1199.  *
  1200.  *        getsockname returns the current name for the  socket s.
  1201.  *        Namelen should  be initialized to
  1202.  *        indicate the amount of space pointed to by name.  On  return
  1203.  *        it contains the actual size of the name returned (in bytes).
  1204.  *        
  1205.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1206.  */
  1207.  
  1208. int s_getsockname(
  1209.     Int4 s,
  1210.     struct sockaddr *name,
  1211.     Int4 *namelen)
  1212. {
  1213. #if SOCK_DEBUG >= 3
  1214.     dprintf("GETSOCKNAME: %d\n", s);
  1215. #endif
  1216.     if (! sock_good_fd(s))
  1217.         return(sock_err(EBADF));
  1218.  
  1219.     if (! goodptr(name))
  1220.         return(sock_err(EFAULT));
  1221.         
  1222.     if (*namelen < 0)
  1223.         return(sock_err(EINVAL));
  1224.  
  1225.     sock_copy_addr(&sockets[s].sa, name, namelen);
  1226.     return(0);
  1227. }
  1228.  
  1229. /*
  1230.  *    s_getpeername(s, name, namelen)
  1231.  *
  1232.  *        getpeername returns the name of the peer connected to socket s.
  1233.  *
  1234.  *        The  int  pointed  to  by the namelen parameter
  1235.  *        should be  initialized  to  indicate  the  amount  of  space
  1236.  *        pointed  to  by name.  On return it contains the actual size
  1237.  *        of the name returned (in bytes).  The name is  truncated  if
  1238.  *        the buffer provided is too small.
  1239.  *        
  1240.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1241.  */
  1242. int s_getpeername(
  1243.     Int4 s,
  1244.     struct sockaddr *name,
  1245.     Int4 *namelen)
  1246. {
  1247.     SocketPtr sp;
  1248.  
  1249. #if SOCK_DEBUG >= 2
  1250.     dprintf("getpeername: socket %d\n", s);
  1251. #endif
  1252.     if (! sock_good_fd(s))
  1253.         return(sock_err(EBADF));        
  1254.  
  1255.     sp = sockets+s;
  1256.     if (! is_used (sp))
  1257.         return (sock_err (EBADF));
  1258.  
  1259.     if (! goodptr(name))
  1260.         return(sock_err(EFAULT));
  1261.         
  1262.     if (*namelen < 0)
  1263.         return(sock_err(EINVAL));
  1264.  
  1265.     if (sp->sstate != SOCK_STATE_CONNECTED) 
  1266.         return(sock_err(ENOTCONN));
  1267.  
  1268.     sock_copy_addr(&sockets[s].peer, name, namelen);
  1269.  
  1270.     return(0);
  1271. }
  1272.  
  1273. /*
  1274.  *    s_shutdown(s, how)
  1275.  *
  1276.  *        shutdown call causes all or part of a full-duplex
  1277.  *        connection on the socket s to be shut down.  If
  1278.  *        how is 0, then further receives will be disallowed.  If  how
  1279.  *        is  1,  then further sends will be disallowed.  If how is 2,
  1280.  *        then further sends and receives will be disallowed.
  1281.  *        
  1282.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1283.  */
  1284. int s_shutdown(
  1285.     Int4 s,
  1286.     Int4 how)
  1287. {
  1288.     SocketPtr sp;
  1289.     
  1290. #if SOCK_DEBUG >= 2
  1291.     dprintf("shutdown: shutdown %d\n", s);
  1292. #endif
  1293.     if (! sock_good_fd(s))
  1294.         return(sock_err(EBADF));
  1295.     sp = sockets+s;
  1296.  
  1297.     switch(how) 
  1298.     {
  1299.         case 0 : 
  1300.             sp->status |= SOCK_STATUS_NOREAD;
  1301.             break;
  1302.             
  1303.         case 1 : 
  1304.             sp->status |= SOCK_STATUS_NOWRITE;
  1305.             break;
  1306.  
  1307.         case 2 :
  1308.             sp->status |= SOCK_STATUS_NOREAD | SOCK_STATUS_NOWRITE;
  1309.             break;
  1310.             
  1311.         default :
  1312.             return(sock_err(EINVAL));
  1313.     }
  1314.     return(0);
  1315. }
  1316.  
  1317. /*
  1318.  *    fcntl() operates on the socket s according to the order in cmd:
  1319.  *
  1320.  *        F_DUPFD    Like Dup. Returns a new descriptor which refers to the 
  1321.  *                same MacTCP stream as s and has the same descriptor 
  1322.  *                status.
  1323.  *
  1324.  *        F_GETFL    returns the descriptor status flags for s. The only
  1325.  *                flag supported is FNDELAY for non-blocking i/o.
  1326.  *
  1327.  *        F_SETFL    sets descriptor status flags for s. The only
  1328.  *                 flag supported is FNDELAY for non-blocking i/o.
  1329.  *
  1330.  *        A dup or F_DUPFD operation copies the descriptor status flags
  1331.  *        maintained by F_SETFL, but once the copy is done, the two are
  1332.  *        disjoint. THIS IS DIFFERENT FROM UNIX.
  1333.  *
  1334.  *        Upon successful completion, the value  returned  depends  on
  1335.  *        cmd as follows:
  1336.  *            F_DUPFD   A new descriptor.
  1337.  *             F_GETFL   Value of flags.
  1338.  *            F_SETFL   0.
  1339.  *
  1340.  *        On error, a value of -1  is returned and errno is set to indicate 
  1341.  *        the error.
  1342.  *
  1343.  *        EBADF           s is not a valid open descriptor.
  1344.  *
  1345.  *        EMFILE          cmd is F_DUPFD and socket descriptor table is full.
  1346.  *
  1347.  *        EINVAL          cmd is F_DUPFD and arg  is  negative  or
  1348.  *                      greater   than   the  maximum  allowable
  1349.  *                      number (see getdtablesize).
  1350.  */
  1351. int s_fcntl(
  1352.     Int4 s,
  1353.     unsigned Int4 cmd,
  1354.     Int4 arg)
  1355. {
  1356. #if SOCK_DEBUG >= 2
  1357.     dprintf("s_fcntl: %d\n", s);
  1358. #endif
  1359.  
  1360.     if (! sock_good_fd(s))
  1361.         return(sock_err(EBADF));
  1362.  
  1363.     switch(cmd) 
  1364.     {
  1365.         /*
  1366.          * Duplicate a socket.
  1367.          */
  1368.         case F_DUPFD : 
  1369.         {
  1370.             int s1;
  1371.             
  1372.             if (arg < 0 || arg >= NUM_SOCKETS)
  1373.                 return(sock_err(EINVAL));
  1374.             
  1375.             s1 = sock_free_fd(arg);
  1376.             if (s1 == -1)
  1377.                 return(sock_err(EMFILE));
  1378.             
  1379.             sock_dup_fd(s,s1);
  1380.             return(s1);
  1381.         }
  1382.         
  1383.         /*
  1384.          *  Get socket status.  This is like getsockopt().
  1385.          *  Only supported descriptor status is FNDELAY.
  1386.          */
  1387.         case F_GETFL : 
  1388.         {
  1389.             SocketPtr sp;
  1390.     
  1391.             sp = sockets+s;
  1392.             if (sp->nonblocking)
  1393.                 return(FNDELAY);
  1394.             else
  1395.                 return(0);
  1396.         }
  1397.         
  1398.         /*
  1399.          *  Set socket status.  This is like setsockopt().
  1400.          *  Only supported descriptor status is FNDELAY.
  1401.          */
  1402.         case F_SETFL : 
  1403.         {
  1404.             SocketPtr sp;
  1405.     
  1406.             sp = sockets+s;
  1407.             if (arg & FNDELAY)
  1408.                 sp->nonblocking = true;
  1409.             else
  1410.                 sp->nonblocking = false;
  1411.             
  1412.             return(0);
  1413.         }
  1414.     }
  1415. }
  1416.  
  1417. /*
  1418.  *    dup(s)
  1419.  *
  1420.  *    dup2(s, news)
  1421.  *
  1422.  *        dup() duplicates an existing socket descriptor.   The  argu-
  1423.  *        ment s is a small non-negative integer index in the per-
  1424.  *        process descriptor table.  The value must be less  than  the
  1425.  *        size  of  the  table, which is returned by getdtablesize(2).
  1426.  *        The new descriptor returned by the call is the  lowest  num-
  1427.  *        bered  descriptor  that  is not currently in use by the pro-
  1428.  *        cess.
  1429.  *
  1430.  *        In the second form  of  the  call,  the  value  of  the  new
  1431.  *        descriptor  desired  is  specified.   If  that descriptor is
  1432.  *        already in use, the descriptor is first deallocated as if  a
  1433.  *        close(2) call had been done first.
  1434.  *
  1435.  *        The value -1 is returned if an error occurs in either  call.
  1436.  *        The  external  variable  errno  indicates  the  cause of the
  1437.  *        error.
  1438.  *
  1439.  *        EBADF               s or  news is  not  a  valid  socket
  1440.  *                            descriptor.
  1441.  *
  1442.  *        EMFILE              Too many descriptors are active.
  1443.  */
  1444. int s_dup(
  1445.     Int4 s)
  1446. {
  1447.     return(s_fcntl(s, F_DUPFD, 0));
  1448. }
  1449.  
  1450. int s_dup2(
  1451.     Int4 s,
  1452.     Int4 s1)
  1453. {
  1454.     if (! sock_good_fd(s))
  1455.         return(sock_err(EBADF));
  1456.  
  1457.     if (s1 < 0 || s1 >= NUM_SOCKETS)
  1458.         return(sock_err(EBADF));
  1459.  
  1460.     if (is_used(sockets+s1))
  1461.     {
  1462.         if (s_close(s1) == -1)
  1463.             return(-1);
  1464.     }
  1465.     sock_dup_fd(s,s1);
  1466.     return(s1);
  1467. }
  1468.  
  1469.  
  1470. /*
  1471.  * s_Ioctl()
  1472.  */
  1473. int s_ioctl(
  1474.     Int4 d,
  1475.     Int4 request,
  1476.     Int4 *argp)
  1477. {
  1478.     struct    ifreq    *ifr;
  1479.     TCPiopb        *tpb;
  1480.     SocketPtr    sp;
  1481.     int            size;
  1482.  
  1483. #if SOCK_DEBUG >= 2
  1484.     dprintf("s_ioctl: %d, request %d\n", d,request);
  1485. #endif
  1486.  
  1487.     if (! sock_good_fd(d))
  1488.         return(sock_err(EBADF));
  1489.  
  1490.     sp = sockets+d;
  1491.     
  1492.     /*
  1493.      * Interpret high order word to find amount of data to be copied 
  1494.      * to/from the user's address space.
  1495.      */
  1496.     size =(request &~(IOC_INOUT | IOC_VOID)) >> 16;
  1497.     
  1498.     /*
  1499.      * Zero the buffer on the stack so the user gets back something deterministic.
  1500.      */
  1501.     if ((request & IOC_OUT) && size)
  1502.         bzero((void *)argp, size);
  1503.  
  1504.     ifr =(struct ifreq *)argp;
  1505.     switch(request) 
  1506.     {
  1507.         /* Non-blocking I/O */
  1508.         case FIONBIO:
  1509.             sp->nonblocking = *(Boolean *)argp;
  1510.             return(0);
  1511.  
  1512.          /* Number of bytes on input Q */
  1513.         case FIONREAD:
  1514.             tpb = sock_fetch_pb(sp);
  1515.             sp->dataavail = xTCPBytesUnread(sp);
  1516.             *(int *)argp=sp->dataavail;
  1517.             return 0;
  1518.  
  1519. #ifdef IOCTL_LATER    
  1520.         /*
  1521.          *    Get interface list.  Pass in buffer and buffer length.
  1522.          *    Returns list of length one of ifreq's 
  1523.          */
  1524.         case SIOCGIFCONF: 
  1525.         {    
  1526.             struct ifconf *ifc =(struct ifconf *)argp;
  1527.             struct ifreq *req = ifc->ifc_req;
  1528.             int reqlen;
  1529.             struct sockaddr_in *addr;
  1530.             
  1531.             /*
  1532.              *    Fill in req fields for the IF's name and local IP addr.
  1533.              */
  1534.             strncpy(req->ifr_name, myIFName, IFNAMSIZ);
  1535.             addr =(struct sockaddr_in *)&req->ifr_addr;
  1536.             addr->sin_family         = AF_INET;
  1537.             addr->sin_addr.s_addr    = myIPAddress;
  1538.             addr->sin_port            = 0;
  1539.             bzero(addr->sin_zero, sizeof(addr->sin_zero));
  1540.             ifc->ifc_len = sizeof(*req);
  1541.                     
  1542.             return(0);            
  1543.         }
  1544.  
  1545.         /*
  1546.          *    Returns MTU of specified IF.
  1547.          */
  1548.         case SIOCGIFMTU: 
  1549.         {    
  1550.             /* don't check IF specification - we only have one anyway */
  1551.             *(int *)ifr->ifr_data= xMaxMTU();
  1552.             return(0);
  1553.         }
  1554.         
  1555.         /*
  1556.          *    Returns local IP Address of IF
  1557.          */
  1558.         case SIOCGIFADDR: 
  1559.         {
  1560.             struct sockaddr_in *addr;
  1561.             
  1562.             /* don't check IF specification - we only have one anyway */
  1563.  
  1564.             addr = &ifr->ifr_addr;
  1565.             addr->sin_addr.s_addr = xIPAddr();
  1566.             addr->sin_family = AF_INET;
  1567.             return(0);
  1568.         }
  1569.  
  1570.         case SIOCGIFDSTADDR:         /* For point to point, which we don't support */
  1571.             return(sock_err(EINVAL));
  1572.  
  1573.         case SIOCGIFFLAGS:             /* Returns IF flags(none yet) */
  1574.             ifr->ifr_flags = 0;
  1575.             return(0);
  1576.             
  1577.         /*
  1578.          *    Return broadcast address - net address plus all ones in host part
  1579.          */
  1580.         case SIOCGIFBRDADDR:     
  1581.         {
  1582.             struct sockaddr_in *addr;
  1583.             
  1584.             /* don't check IF specification */
  1585.             /* we only have one and its broadcast  */
  1586.                 
  1587.             addr = &ifr->ifr_addr;
  1588.             addr->sin_addr.s_addr = xIPAddr() | ~xNetMask();
  1589.             return(0);
  1590.         }
  1591. #endif IOCTL_LATER    
  1592.         default :
  1593.             return(sock_err(EOPNOTSUPP));
  1594.     }
  1595. }
  1596.  
  1597. /*
  1598.  *    s_setsockopt()
  1599.  *
  1600.  *        Set socket options. None implemented. In Unix there are...
  1601.  *
  1602.  *          SO_REUSEADDR        toggle local address reuse
  1603.  *          SO_KEEPALIVE        toggle keep connections alive
  1604.  *          SO_DONTROUTE        toggle routing bypass for  outgoing
  1605.  *                              messages
  1606.  *          SO_LINGER           linger on close if data present
  1607.  *          SO_BROADCAST        toggle   permission   to   transmit
  1608.  *                              broadcast messages
  1609.  *          SO_OOBINLINE        toggle  reception  of   out-of-band
  1610.  *                              data in band
  1611.  *          SO_SNDBUF           set buffer size for output
  1612.  *          SO_RCVBUF           set buffer size for input
  1613.  *          SO_TYPE             get the type  of  the  socket  (get
  1614.  *                              only)
  1615.  *          SO_ERROR            get and clear error on  the  socket
  1616.  *                             (get only)
  1617.  */
  1618. int s_setsockopt(
  1619.     Int4 s,
  1620.     Int4 level,
  1621.     Int4 optname,
  1622.     char *optval,
  1623.     Int4 optlen)
  1624. {
  1625. #pragma unused(optval)
  1626. #pragma unused(optlen)
  1627.     SocketPtr sp;
  1628.  
  1629. #if SOCK_DEBUG >= 3
  1630.     dprintf("SETSOCKOPT:  socket: %d  option: %d  \n", s,optname);
  1631. #endif
  1632.     if (! sock_good_fd(s))
  1633.         return(sock_err(EBADF));
  1634.  
  1635.     sp = sockets+s;
  1636.  
  1637.     /*
  1638.      * demultiplex to socket option handlers at other protocol levels.(None
  1639.      * supported yet).
  1640.      */
  1641.     switch(level) 
  1642.     {
  1643.         case SOL_SOCKET :         /* socket level option */
  1644.             switch(optname) 
  1645.             {
  1646.                 default :
  1647.                     return(0);
  1648.             }
  1649.             break;
  1650.         case IPPROTO_TCP:
  1651.             switch(optname)
  1652.             {
  1653.                 default:
  1654.                     return(0);
  1655.             }
  1656.             break;
  1657.         default :
  1658.             return(sock_err(ENOPROTOOPT));
  1659.     }
  1660.     return(0);
  1661. }
  1662.  
  1663.  
  1664. /*
  1665.  * s_setspin() - define a routine to be called repeatedly when
  1666.  *                 socket routines are blocked (ie. spinning)
  1667.  *
  1668.  *                 pass a NULL pointer to turn off a previously
  1669.  *                 defined spin routine.
  1670.  */
  1671. int s_setspin(
  1672.     SpinFn routine)
  1673. {
  1674.     if (routine == NULL || goodptr(routine))
  1675.         {
  1676.         spinroutine = routine;
  1677.         return(0);
  1678.         }
  1679.     else
  1680.         return(sock_err(EFAULT));
  1681. }
  1682.  
  1683. /*
  1684.  * s_getspin() - returns current spinroutine
  1685.  */
  1686. SpinFn s_getspin()
  1687.     {
  1688.     return (spinroutine);
  1689.     }
  1690.     
  1691. int defaultSpin(spin_msg msg,long param)
  1692.     {
  1693. #pragma unused (msg,param)
  1694.     EventRecord evrec;
  1695.     
  1696.     WaitNextEvent(0, &evrec, 1 /* ticks */, NULL);
  1697.     return 0;        /* return non-zero to exit current routine */
  1698.     }
  1699.